CS 116: Introduction to Computer Science 2

CS 116 Tutorial 10 (Solutions): Reading and Writing Files

Reminders:

  • Assignment 09 is due on Monday, Dec 2nd at 10:00pm

Tutorial Solutions

class CD: ''' Fields: artist (Str), duration (Nat), songs (listof Str) where * artist is the name of the performer of the album * duration is the length of the CD in seconds * songs contains the names of the songs on the CD. ''' def __init__(self, artist, dur, los): ''' [purpose]: Initializes a CD [fields]: * artist (artist's name) - Str * duration (duration of CD in seconds) - Nat * songs (list of artist's songs) - (listof Str) ''' self.artist = artist self.duration = dur self.songs = los def __repr__(self): ''' [purpose]: Represents a CD [format]: Artist's Name: XXX Duration: XXX Songs: XXX ''' songstr = "" for song in self.songs: songstr += song + ", " songstr = songstr[:-2] return "Artist Name: {0}\nDuration: {1}\nSongs: {2}".format\ (self.artist, self.duration, songstr) def __eq__(self, other): return isinstance(other, CD) \ and self.artist == other.artist \ and self.duration == other.duration \ and self.songs == other.songs

  1. Write the Python function make_cd_dict that reads the data from a text file and returns a dictionary of CD objects containing the data from the file, with keys equal to the name of the CD.
    { album title: CD(artist, duration, [listof songs]) }
    - You may assume that each CD has a unique name.
    - The files will be formatted in the following way:

    name of artist, name of CD, length in seconds, song titles
    (separated by a comma and at least one space).

    Example File:

    Yes, Close to the Edge, 2266, Close to the Edge, And You and I, Siberian Khatru
    Various, Disney Mix, 912, You'll Be in My Heart, Kiss the Girl, Circle of Life, I'll Make a Man Out of You, Whole New World, Go the Distance
    Pink Floyd, Wish You Were Here (Side 1), 1268, Shine On You Crazy Diamond (1-5), Welcome to the Machine
    Jonathan Coulton, Code Monkey, 203, Code Monkey
    The Beatles, Abbey Road, 255, Mean Mr. Mustard, Polythene Pam, She Came in Through the Bathroom Window

    Solution using readline:

    import check # Dictionaries for testing d2 = {"The Final Countdown": CD("Europe", 227, ["The Final Countdown"])} d3 = {"Disney Mix": CD("Various", 912, ["You'll Be in My Heart", "Kiss the Girl", "Circle of Life", "I'll Make a Man Out of You", "Whole New World", "Go the Distance"]), "Code Monkey": CD("Jonathan Coulton", 203, ["Code Monkey"]), "Close to the Edge": CD("Yes", 2266, ["Close to the Edge", "And You and I", "Siberian Khatru"]), "Wish You Were Here (Side 1)": CD("Pink Floyd", 1268, ["Shine On You Crazy Diamond (1-5)", "Welcome to the Machine"]), "Abbey Road": CD("The Beatles", 255, ["Mean Mr. Mustard", "Polythene Pam", "She Came in Through the Bathroom Window"])} def make_cd_dict(fname): ''' reads data from a file called fname and outputs a dictionary of CD objects Effects: reads data from a file and creates a dict of CD objects from the data make_cd_dict: Str -> (dictof Str CD) Examples: If the file is blank, the function will produce {} make_cd_list("made_cd_dict_2.txt") => d2 ''' new_dict = {} f = open(fname, 'r') line = f.readline() while line != "": fields = line.split(",") cd_fields = list(map(str.strip, fields)) artist = cd_fields[0] title = cd_fields[1] dur = int(cd_fields[2]) songs = cd_fields[3:] new_dict[title] = CD(artist, dur, songs) line = f.readline() f.close() return new_dict # Blank File check.expect("Test 1", make_cd_dict("make_cd_dict_1.txt"), {}) # File with one CD check.expect("Test 2", make_cd_dict("make_cd_dict_2.txt"), d2) #File with multiple CDs check.expect("Test 3", make_cd_dict("make_cd_dict_3.txt"), d3)

    Solution using readlines:

    import check def make_cd_dict(fname): ''' reads data from a file called fname and outputs a dictionary of CD objects Effects: reads data from a file and creates a dict of CD objects from the data make_cd_dict: Str -> (dictof Str CD) Examples: If the file is blank, the function will produce {} make_cd_list("made_cd_dict_2.txt") => d2 ''' f = open(fname, 'r') data = f.readlines() f.close() new_dict = {} for cd in data: fields = cd.split(",") cd_fields = list(map(str.strip, fields)) artist = cd_fields[0] title = cd_fields[1] dur = int(cd_fields[2]) songs = cd_fields[3:] new_dict[title] = CD(artist, dur, songs) return new_dict # Blank File check.expect("Test 1", make_cd_dict("make_cd_dict_1.txt"), {}) # File with one CD check.expect("Test 2", make_cd_dict("make_cd_dict_2.txt"), d2) #File with multiple CDs check.expect("Test 3", make_cd_dict("make_cd_dict_3.txt"), d3)
  2. Write the Python function output_CD_info that consumes a dictionary of CD objects (like the one returned in Q1) and a string.
    If the string is not a key in the dictionary, the function should do nothing.
    If the string is a key in the dictionary, the function should create a text file named "Artist - Title".txt, where Artist and Title relate to the cd found at cd_dict[name].
    The text file should contain (each on its own line):

    • the title of the CD in uppercase,
    • then the artist,
    • then the duration of the CD (formatted like in question 1),
    • then a blank line, and
    • then the index of the song with name of each track in the CD.

    d = {"Disney Mix": CD("Various", 912, ["You'll Be in My Heart", "Kiss the Girl",
                                           "Circle of Life", "I'll Make a Man Out of You",
                                           "Whole New World", "Go the Distance"])}

    For example, output_CD_info(d, "Disney Mix") would create a file named "Various - Disney Mix.txt" containing:

    DISNEY MIX
    Various
    912
    
    1. You'll Be in My Heart
    2. Kiss the Girl
    3. Circle of Life
    4. I'll Make a Man Out of You
    5. Whole New World
    6. Go the Distance

    Solution with write:

    import check
    
    # Dictionaries for testing
    d2 = {"The Final Countdown": CD("Europe", 227, ["The Final Countdown"])}
    d3 = {"Disney Mix": CD("Various", 912, ["You'll Be in My Heart", "Kiss the Girl",
                                            "Circle of Life", "I'll Make a Man Out of You",
                                            "Whole New World", "Go the Distance"]),
          "Code Monkey": CD("Jonathan Coulton", 203, ["Code Monkey"]),
          "Close to the Edge": CD("Yes", 2266, ["Close to the Edge", "And You and I", "Siberian Khatru"]),
          "Wish You Were Here (Side 1)": CD("Pink Floyd", 1268, ["Shine On You Crazy Diamond (1-5)",
                                                                 "Welcome to the Machine"]),
          "Abbey Road": CD("The Beatles", 255, ["Mean Mr. Mustard",
                                                "Polythene Pam",
                                                "She Came in Through the Bathroom Window"])}
    
    
    def output_CD_info(cd_dict, name):
        '''
        writes the data from the CD object associated with that name to
        a new file named "Artist - Title.txt" if name is a key in cd_dict.
        Effects: writes a file if name is in cd_dict
    
        output_CD_info: (dictof Str CD) Str -> None
    
        Examples:
        output_CD_info(d2, "The Final Countdown") will create a file called
        "Europe - The Final Countdown.txt" with THE FINAL COUNTDOWN on its first
        line, Europe on its second line, 227 sec on the third line, a blank fourth
        line, and 1. The Final Countdown on its fifth (and final) line
        output_CD_info(d3, "Disney Mix") will create a file called "Various - Disney Mix.txt"
        with DISNEY MIX on its first line, Various on its second line, 912 sec on the third
        line, a blank fourth line, and a list of tracks on the following line in the form: 3.
        Circle of Life
        '''
        if name in cd_dict:
            cd = cd_dict[name]
        else:
            return None
    
        filename = "{0} - {1}.txt".format(cd.artist, name)
        f = open(filename, 'w')
    
        f.write("{0}\n".format(name.upper()))
        f.write("{0}\n".format(cd.artist))
        f.write("{0} sec\n".format(cd.duration))
        f.write("\n")
    
        for i in range(len(cd.songs)):
            f.write("{0}. {1}\n".format(i+1, cd.songs[i]))
    
        f.close()
    
    # TESTING:
    check.expect("Test 1", output_CD_info({}, "Aquarium"), None)
    check.expect("Test 2", output_CD_info(d3, "Aquarium"), None)
    # No file was created by the previous two tests
    check.set_file_exact("Europe - The Final Countdown.txt","output_CD_info_3.txt")
    check.expect("Test 3", output_CD_info(d2, "The Final Countdown"), None)
    check.set_file_exact("The Beatles - Abbey Road.txt","output_CD_info_4.txt")
    check.expect("Test 4", output_CD_info(d3, "Abbey Road"), None)
    

    Solution with writelines:

    import check
    
    # Dictionaries for testing
    d2 = {"The Final Countdown": CD("Europe", 227, ["The Final Countdown"])}
    d3 = {"Disney Mix": CD("Various", 912, ["You'll Be in My Heart", "Kiss the Girl",
                                            "Circle of Life", "I'll Make a Man Out of You",
                                            "Whole New World", "Go the Distance"]),
          "Code Monkey": CD("Jonathan Coulton", 203, ["Code Monkey"]),
          "Close to the Edge": CD("Yes", 2266, ["Close to the Edge", "And You and I", "Siberian Khatru"]),
          "Wish You Were Here (Side 1)": CD("Pink Floyd", 1268, ["Shine On You Crazy Diamond (1-5)",
                                                                 "Welcome to the Machine"]),
          "Abbey Road": CD("The Beatles", 255, ["Mean Mr. Mustard",
                                                "Polythene Pam",
                                                "She Came in Through the Bathroom Window"])}
    
    
    def output_CD_info(cd_dict, name):
        '''
        writes the data from the CD object associated with that name to a
        new file named "artist - title.txt" if name is a key in cd_dict.
        Effects: writes a file if name is in cd_dict
    
        output_CD_info: (dictof Str CD) Str -> None
    
        Examples:
        output_CD_info(d2, "The Final Countdown") will create a file called
        "Europe - The Final Countdown.txt" with THE FINAL COUNTDOWN on its first
        line, Europe on its second line, 227 sec on the third line, a blank fourth
        line, and 1. The Final Countdown on its fifth (and final) line
        output_CD_info(d3, "Disney Mix") will create a file called "Various - Disney Mix.txt"
        with DISNEY MIX on its first line, Various on its second line, 912 sec on the
        third line, a blank fourth line, and a list of tracks on the following line
        in the form: 3. Circle of Life
        '''
        if name in cd_dict:
            cd = cd_dict[name]
        else:
            return None
    
        filename = "{0} - {1}.txt".format(cd.artist, name)
    
        output = ["{0}\n".format(name.upper()),
        		  "{0}\n".format(cd.artist),
       			  "{0} sec\n".format(cd.duration),
        		  "\n"]
        for i in range(len(cd.songs)):
            output.append("{0}. {1}\n".format(i+1, cd.songs[i]))
    
    	f = open(filename, 'w')
    	f.writelines(output)
        f.close()
    
    # TESTING:
    check.expect("Test 1", output_CD_info({}, "Aquarium"), None)
    check.expect("Test 2", output_CD_info(d3, "Aquarium"), None)
    # No file was created by the previous two tests
    check.set_file_exact("Europe - The Final Countdown.txt","output_CD_info_3.txt")
    check.expect("Test 3", output_CD_info(d2, "The Final Countdown"), None)
    check.set_file_exact("The Beatles - Abbey Road.txt","output_CD_info_4.txt")
    check.expect("Test 4", output_CD_info(d3, "Abbey Road"), None)
    

Valid XHTML 1.0 Strict

Last modified on Friday, 20 December 2019, at 14:04.